package com.fingard.dsp.bank.directbank.spdb01.authforrec;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 根据文件生成xml报文（单例）
 *
 * @author T-chenqy
 */
public class XMLFillValueHelper {
    private static XMLFillValueHelper th;
    /**
     * 文件列表
     */
    private Map<String, Document> docs;

    private XMLFillValueHelper() {
        docs = new HashMap<String, Document>();
    }

    public static XMLFillValueHelper getInstance() {
        if (th == null) {
            th = new XMLFillValueHelper();
        }
        return th;
    }

    /**
     * 构建xml
     *
     * @param fileName
     * @param param
     * @return
     * @throws DocumentException
     * @throws IOException
     */
    public String buildXML(String fileName, Map<String, Object> param) throws DocumentException, IOException {
        // 获取document
        Document doc = docs.get(fileName);
        if (doc == null) {
            doc = init(fileName);
        }
        doc = (Document) doc.clone();

        // 填充值
        fillValue(doc.getRootElement(), param);
        return doc.asXML();
    }

    /**
     * 读取这个目录（packageSend/resource/xml）下的文件
     *
     * @param fileName
     * @return
     * @throws DocumentException
     * @throws IOException
     */
    private Document init(String fileName) throws DocumentException, IOException {
        SAXReader reader = new SAXReader();
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("resource/xml/" + fileName);

        Document doc = reader.read(in);
        docs.put(fileName, doc);
        in.close();
        return doc;
    }

    /**
     * 给xml中填值
     *
     * @param root
     * @param param
     * @param loopNode
     */
    @SuppressWarnings("unchecked")
    private void fillValue(Element root, Map<String, Object> param) {
        List<Element> eles = root.elements();
        String nodeName = root.getName();
        if (eles != null && eles.size() > 0) {
            Object obj = param.get(nodeName);
            if (obj != null && obj instanceof List) {
                // 存在循环节点，循环节点处理
                fillLoopNodeValue(root, param);
                return;
            }

            for (Element item : eles) {
                fillValue(item, param);
            }
        } else {
            String value = StringUtils.objectToString(param.get(nodeName));
            if (value != null) {
                root.setText(value);
            }
        }
    }

    /**
     * 循环节点处理
     *
     * @param root
     * @param param
     * @param loopNode
     */
    @SuppressWarnings("unchecked")
    private void fillLoopNodeValue(Element root, Map<String, Object> param) {
        String nodeName = root.getName();
        List<Map<String, Object>> items = (List<Map<String, Object>>) param.get(nodeName);
        if (items == null) {
            return;
        }
        int itemsLen = items.size();

        Element parent = root.getParent();
        // 增加循环节点
        while (itemsLen > 1) {
            itemsLen--;
            parent.add((Element) root.clone());
        }

        // 向循环节点加值
        List<Element> lpNodes = parent.elements();
        for (int i = 0; i < items.size(); i++) {
            // 获取一个循环节点的Map值
            Map<String, Object> item = items.get(i);
            // 获取一个循环节点
            Element lpNode = lpNodes.get(i);
            // 获取循环节点的子节点
            List<Element> lpNodeChildren = lpNode.elements();
            // 遍历子节点赋值
            for (Element lpNodeChild : lpNodeChildren) {
                fillValue(lpNodeChild, item);
            }
        }
    }
}
